package tools.clustering.isodata;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import tools.fasta.fastaParser;

public class prepareInfile {

	HashMap<String, Integer> names_number;
	HashMap<Integer, String> number_names;
	HashMap<String, Integer> lengths;
	double[][] distance;
	
	public static void main(String[] args)throws Exception{
		if(args.length==0){
			System.out.println(printHelp());
			System.exit(616);
		}else{
			if(args[0].equals("prepareInfile")){
				if(args.length==3){
					prepareInfile p=new prepareInfile(args[1],true);
					p.printFiles(args[2]);
				}else{
					System.out.println(printHelp());
					System.exit(616);
				}
			}else if(args[0].equals("prepnorm")){
				if(args.length==4){
					prepareInfile p=new prepareInfile(args[1],args[2]);
					p.printFiles(args[3]);
				}else{
					System.out.println(printHelp());
					System.exit(616);
				}
			}else{
				System.out.println(printHelp());
				System.exit(616);
			}
			
		}
		System.exit(0);
	}
	public static String printHelp(){
		String help="prepareInfile - parses and normalises on alignmentlength\n"; 
		help+="\tcmd <infile> <outprefix>\n";
		help+="prepnorm - parses and normalizes on sequencelength\n";
		help+="\tcmd <fafile> <infile> <outprefix>\n";
		
		return help;
	}
	
	public prepareInfile(String fastafile,String inFile)throws Exception{
		lengths=new HashMap<String, Integer>();
		fastaParser fp=new fastaParser(new BufferedReader(new FileReader(fastafile)));
		for(;fp.hasNext();){
			String s=fp.nextHit();
			lengths.put(s.substring(1).split(" ")[0], fp.getSeq().length());
		}
		BufferedReader in=new BufferedReader(new FileReader(inFile));
		names_number=new HashMap<String, Integer>();
		int clusterNr=0,lineNr=0;
		String[] items;
		for(String s=in.readLine();s!=null&&s.length()>2;s=in.readLine(),lineNr++){
			if (lineNr%1000000==0) {
				System.out.println("Run 1: "+lineNr);
			}
			items=prepNorm(s);
			if (!names_number.containsKey(items[0])) {
				names_number.put(items[0], new Integer(clusterNr));
				clusterNr++;
			}
		}
		distance=new double[clusterNr][clusterNr];
		in.close();
		BufferedReader in2=new BufferedReader(new FileReader(inFile));
		lineNr=0;
		for(String s=in2.readLine();s!=null&&s.length()>2;s=in2.readLine(),lineNr++){
			if (lineNr%1000000==0) {
				System.out.println("Run 2: "+lineNr);
			}
			items=lineToItem(s);
			if (!names_number.containsKey(items[0])) {
				System.out.println("key 1 missing: "+items[0]);
				System.out.println("key 2: "+items[1]);
			}
			if (!names_number.containsKey(items[1])) {
				System.out.println("key 2 missing: "+items[1]);
				System.out.println("key 1: "+items[0]);
			}
//			i=names_number.get(items[0]).intValue();
//			j=names_number.get(items[1]).intValue();
//			d=Double.parseDouble(items[2]);
//			distance[i][j]=d;
//			distance[j][i]=d;
			distance[names_number.get(items[0]).intValue()][names_number.get(items[1]).intValue()]=Double.parseDouble(items[2]);
			distance[names_number.get(items[1]).intValue()][names_number.get(items[0]).intValue()]=Double.parseDouble(items[2]);
			
		}
		
	}
	
	public prepareInfile(String inFile,boolean memoryCheap)throws Exception{
		BufferedReader in=new BufferedReader(new FileReader(inFile));
		names_number=new HashMap<String, Integer>();
		int clusterNr=0,lineNr=0;
		String[] items;
		for(String s=in.readLine();s!=null&&s.length()>2;s=in.readLine(),lineNr++){
			if (lineNr%1000000==0) {
				System.out.println("Run 1: "+lineNr);
			}
			items=lineToItem(s);
			if (!names_number.containsKey(items[0])) {
				names_number.put(items[0], new Integer(clusterNr));
				clusterNr++;
			}
		}
		distance=new double[clusterNr][clusterNr];
		in.close();
		BufferedReader in2=new BufferedReader(new FileReader(inFile));
		lineNr=0;
		for(String s=in2.readLine();s!=null&&s.length()>2;s=in2.readLine(),lineNr++){
			if (lineNr%1000000==0) {
				System.out.println("Run 2: "+lineNr);
			}
			items=lineToItem(s);
			if (!names_number.containsKey(items[0])) {
				System.out.println("key 1 missing: "+items[0]);
				System.out.println("key 2: "+items[1]);
			}
			if (!names_number.containsKey(items[1])) {
				System.out.println("key 2 missing: "+items[1]);
				System.out.println("key 1: "+items[0]);
			}
//			i=names_number.get(items[0]).intValue();
//			j=names_number.get(items[1]).intValue();
//			d=Double.parseDouble(items[2]);
//			distance[i][j]=d;
//			distance[j][i]=d;
			distance[names_number.get(items[0]).intValue()][names_number.get(items[1]).intValue()]=Double.parseDouble(items[2]);
			distance[names_number.get(items[1]).intValue()][names_number.get(items[0]).intValue()]=Double.parseDouble(items[2]);
			
		}
	}
	
	public prepareInfile(String Infile)throws Exception{
		BufferedReader in=new BufferedReader(new FileReader(Infile));
		names_number=new HashMap<String, Integer>();
		number_names=new HashMap<Integer, String>();
		ArrayList<double[]> tmp=new ArrayList<double[]>();
		int clusterNr=0;
		String[] items;
		int lineNr=0;
		for(String s=in.readLine();s!=null;s=in.readLine(),lineNr++){
			if (lineNr%100000==0) {
				System.out.println(lineNr);
			}
			items=lineToItem(s);
			if (!names_number.containsKey(items[0])){
				names_number.put(items[0],new Integer(clusterNr));
				number_names.put(new Integer(clusterNr),items[0]);
				tmp.add(new double[]{clusterNr,clusterNr,0});
				clusterNr++;
			}
			if (!names_number.containsKey(items[1])){
				names_number.put(items[1],new Integer(clusterNr));
				number_names.put(new Integer(clusterNr),items[1]);
				tmp.add(new double[]{clusterNr,clusterNr,0});
				clusterNr++;
			}
			tmp.add(new double[] {names_number.get(items[0]).doubleValue(),names_number.get(items[1]).doubleValue(),Double.parseDouble(items[2])});
			tmp.add(new double[] {names_number.get(items[1]).doubleValue(),names_number.get(items[0]).doubleValue(),Double.parseDouble(items[2])});
		}
		distance=new double[clusterNr][clusterNr];
		
		for (Iterator iter = tmp.iterator(); iter.hasNext();) {
			double[] item = (double[]) iter.next();
			distance[(int)item[0]][(int)item[1]]=item[2];
		}
	}
	
	public void printFiles(String outFilePrefix)throws Exception{
		BufferedWriter out=new BufferedWriter(new FileWriter(outFilePrefix+"_names.csv"));
		for (Iterator iter = names_number.keySet().iterator(); iter.hasNext();) {
			String s = (String) iter.next();
			out.write(((Integer)names_number.get(s)).intValue()+"\t"+s+"\n");
		}
		out.close();
		out=new BufferedWriter(new FileWriter(outFilePrefix+"_matrix.csv"));
		for(int i=0;i<distance.length;i++){
			for (int j = 0; j < distance[i].length; j++) {
				out.write(distance[i][j]+"\t");
			}
			out.write("\n");
		}
		out.close();
	}
	
	private String[] lineToItem(String line){
		String[] tmp=line.split("\t");
		return new String[] {tmp[0],tmp[1],(double)Double.parseDouble(tmp[9])/((Double.parseDouble(tmp[5]))+Double.parseDouble(tmp[8]))+""};
	}
	private String[] prepNorm(String line){
		String[] tmp=line.split("\t");
		int l1=0,l2=0;
		try{
		l1=lengths.get(tmp[0]);
		}catch (Exception e) {
			System.out.println(tmp[0]);
			System.exit(616);
		}
		try{
		l2=lengths.get(tmp[1]);
		}catch (Exception e) {
			System.out.println(tmp[0]);
			System.exit(616);
		}
		return new String[] {tmp[0],tmp[1],(double)Double.parseDouble(tmp[9])*Double.parseDouble(tmp[5])*(((double)(l2+l1))/(l1*l2))+""};
	}
}
